using System;
using System.Net;
using System.Text;
using System.Threading;
using System.Net.Sockets;

namespace Publish.Services.SocketUdp
{
    /// <summary>
    /// socket 服务器端
    /// </summary>
    public class SocketServer
    {
        #region Field

        /// <summary>
        /// 定义一个当前客户端的socket套链接
        /// </summary>
        private Socket server;

        /// <summary>
        /// 定义监听端口
        /// </summary>
        private int port;

        /// <summary>
        /// 接收到的数据
        /// </summary>
        private StringBuilder receiveData = new StringBuilder();
        /// <summary>
        /// 接收信息字符串尺寸 默认1024字节
        /// </summary>
        private int dataSize = 1024;

        /// <summary>
        /// 错误消息
        /// </summary>
        private String errorMsg = "";

        /// <summary>
        /// 监听的线程
        /// </summary>
        private Thread thread;

        /// <summary>
        /// 完成一个接受的委托
        /// </summary>
        /// <param name="talk"></param>
        /// <param name="e"></param>
        public delegate void CompleteHandler(SocketServer server, EventArgs e);
        /// <summary>
        /// 完成接收事件
        /// </summary>
        public event CompleteHandler ReceiveComplete;

        #endregion

        #region Constructor

        /// <summary>
        /// 构造函数  主要用户初始化本机的socket
        /// </summary>
        public SocketServer()
        {
            Initializion();
        }

        #endregion

        #region Destructor

        /// <summary>
        /// 析构函数 关闭建立的socket
        /// </summary>
        ~SocketServer()
        {
            server.Close();
            thread.Abort();
        }

        #endregion

        #region Property

        /// <summary>
        /// 接收到的数据 只读
        /// </summary>
        public String ReceiveData { get { return receiveData.ToString(); } }

        /// <summary>
        /// 错误消息 为空时表示没有错误
        /// </summary>
        public String ErrorMsg { get { return errorMsg; } }

        #endregion

        #region Method

        #region 初始化本机的Socket

        /// <summary>
        /// 初始化本机的Socket
        /// </summary>
        public void Initializion()
        {
            port = 18181;
            IPEndPoint localPoint = new IPEndPoint(IPAddress.Any, port);
            server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            //绑定本机的网络端点
            server.Bind(localPoint);
        }

        #endregion

        #region 监听

        /// <summary>
        /// 开始监听 新开一个线程
        /// </summary>
        public void StartListen()
        {
            //ThreadStart method = new ThreadStart(ListenMethod);
            ////新开一个线程
            //thread = new Thread(method);
            //thread.Start();

            thread = new Thread(ListenMethod) { IsBackground = true };
            thread.Start();//读取发布历史列表
        }

        /// <summary>
        /// 监听的具体方法
        /// </summary>
        private void ListenMethod()
        {
            //存储数据的字节
            byte[] data = new byte[dataSize];
            //收到信息的长度
            int length = 0;
            //一直进行监听
            while (true)
            {
                try
                {
                    //开始监听
                    server.Listen(10);
                    //接收到远程的连接
                    Socket remoteClient = server.Accept();
                    //重新初始化下接收数据的变量 防止连续接收时数据叠加
                    receiveData = new StringBuilder();
                    while (true)
                    {
                        data = new byte[dataSize];
                        length = remoteClient.Receive(data);
                        //如果没有数据接收 跳出循环
                        if (length != 0)
                        {
                            //存储进数据流中
                            receiveData.Append(Encoding.ASCII.GetString(data, 0, length));
                        }
                        else
                        {
                            //
                            break;
                        }
                    }
                    //关闭远程的socket
                    remoteClient.Close();
                }//这里的异常可以用更加细的  特定的异常来捕捉，这里为了简单全部捕捉了
                catch (Exception ex)
                {
                    errorMsg = "接收出错：" + ex.Message;
                }
                finally
                {
                    //调用接收数据完成的事件
                    ReceiveComplete(this, new EventArgs());
                }
            }
        }

        #endregion

        #endregion
    }
}
